The API of `termcolor` fits what the system gives us much more nicely and should
be well battle-tested from ripgrep. Additionally we don't really need huge
terminfo parsers, that wasn't every really the intention of the color support
here.
"shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
]
[[package]]
-name = "term"
-version = "0.4.5"
+name = "termcolor"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wincolor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "wincolor"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b"
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
-"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
+"checksum termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca"
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773"
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+"checksum wincolor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99c2af1426e2166e6f66d88b09b2a4d63afce06875f149174e386f2f1ee9779b"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
shell-escape = "0.1"
tar = { version = "0.4", default-features = false }
tempdir = "0.3"
-term = "0.4.4"
+termcolor = "0.3"
toml = "0.4"
url = "1.1"
use std::fs;
use std::path::{Path, PathBuf};
-use cargo::core::shell::{Verbosity, ColorConfig};
+use cargo::core::shell::{Shell, Verbosity};
use cargo::util::{self, CliResult, lev_distance, Config, CargoResult, CargoError, CargoErrorKind};
use cargo::util::CliError;
let config = match Config::default() {
Ok(cfg) => cfg,
Err(e) => {
- let mut shell = cargo::shell(Verbosity::Verbose, ColorConfig::Auto);
+ let mut shell = Shell::new();
cargo::exit_with_error(e.into(), &mut shell)
}
};
pub fn execute(options: Options, config: &Config) -> CliResult {
debug!("executing; cmd=cargo-read-manifest; args={:?}",
env::args().collect::<Vec<_>>());
- config.shell().set_color_config(options.flag_color.as_ref().map(|s| &s[..]))?;
+ config.shell().set_color_choice(options.flag_color.as_ref().map(|s| &s[..]))?;
let root = find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())?;
pub use self::package_id_spec::PackageIdSpec;
pub use self::registry::Registry;
pub use self::resolver::Resolve;
-pub use self::shell::{Shell, MultiShell, ShellConfig, Verbosity, ColorConfig};
+pub use self::shell::{Shell, Verbosity};
pub use self::source::{Source, SourceId, SourceMap, GitReference};
pub use self::summary::Summary;
pub use self::workspace::{Workspace, WorkspaceConfig};
use std::fmt;
use std::io::prelude::*;
-use std::io;
-use term::color::{Color, BLACK, RED, GREEN, YELLOW};
-use term::{self, Terminal, TerminfoTerminal, color, Attr};
-
-use self::AdequateTerminal::{NoColor, Colored};
-use self::Verbosity::{Verbose, Quiet};
-use self::ColorConfig::{Auto, Always, Never};
+use termcolor::{self, StandardStream, Color, ColorSpec, WriteColor};
+use termcolor::Color::{Green, Red, Yellow};
use util::errors::CargoResult;
Quiet
}
-#[derive(Clone, Copy, PartialEq)]
-pub enum ColorConfig {
- Auto,
- Always,
- Never
-}
-
-impl fmt::Display for ColorConfig {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- ColorConfig::Auto => "auto",
- ColorConfig::Always => "always",
- ColorConfig::Never => "never",
- }.fmt(f)
- }
-}
-
-#[derive(Clone, Copy)]
-pub struct ShellConfig {
- pub color_config: ColorConfig,
- pub tty: bool
-}
-
-enum AdequateTerminal {
- NoColor(Box<Write + Send>),
- Colored(Box<Terminal<Output=Box<Write + Send>> + Send>)
-}
-
pub struct Shell {
- terminal: AdequateTerminal,
- config: ShellConfig,
+ err: StandardStream,
+ verbosity: Verbosity,
+ choice: ColorChoice,
}
-pub struct MultiShell {
- out: Shell,
- err: Shell,
- verbosity: Verbosity
+#[derive(PartialEq, Clone, Copy)]
+pub enum ColorChoice {
+ Always,
+ Never,
+ CargoAuto,
}
-impl MultiShell {
- pub fn new(out: Shell, err: Shell, verbosity: Verbosity) -> MultiShell {
- MultiShell { out: out, err: err, verbosity: verbosity }
- }
-
- // Create a quiet, basic shell from supplied writers.
- pub fn from_write(out: Box<Write + Send>, err: Box<Write + Send>) -> MultiShell {
- let config = ShellConfig { color_config: ColorConfig::Never, tty: false };
- let out = Shell { terminal: NoColor(out), config: config.clone() };
- let err = Shell { terminal: NoColor(err), config: config };
- MultiShell {
- out: out,
- err: err,
- verbosity: Verbosity::Quiet,
+impl Shell {
+ pub fn new() -> Shell {
+ Shell {
+ err: StandardStream::stderr(ColorChoice::CargoAuto.to_termcolor_color_choice()),
+ verbosity: Verbosity::Verbose,
+ choice: ColorChoice::CargoAuto,
}
}
- pub fn out(&mut self) -> &mut Shell {
- &mut self.out
+ fn print(&mut self,
+ status: &fmt::Display,
+ message: &fmt::Display,
+ color: Color,
+ justified: bool) -> CargoResult<()> {
+ match self.verbosity {
+ Verbosity::Quiet => Ok(()),
+ _ => {
+ self.err.reset()?;
+ self.err.set_color(ColorSpec::new()
+ .set_bold(true)
+ .set_fg(Some(color)))?;
+ if justified {
+ write!(self.err, "{:>12}", status)?;
+ } else {
+ write!(self.err, "{}", status)?;
+ }
+ self.err.reset()?;
+ write!(self.err, " {}\n", message)?;
+ Ok(())
+ }
+ }
}
- pub fn err(&mut self) -> &mut Shell {
+ pub fn err(&mut self) -> &mut StandardStream {
&mut self.err
}
- pub fn say<T: ToString>(&mut self, message: T, color: Color)
- -> CargoResult<()> {
- match self.verbosity {
- Quiet => Ok(()),
- _ => self.out().say(message, color)
- }
- }
-
- pub fn status_with_color<T, U>(&mut self, status: T, message: U, color: Color)
- -> CargoResult<()>
+ pub fn status<T, U>(&mut self, status: T, message: U) -> CargoResult<()>
where T: fmt::Display, U: fmt::Display
{
- match self.verbosity {
- Quiet => Ok(()),
- _ => self.err().say_status(status, message, color, true)
- }
+ self.print(&status, &message, Green, true)
}
- pub fn status<T, U>(&mut self, status: T, message: U) -> CargoResult<()>
+ pub fn status_with_color<T, U>(&mut self,
+ status: T,
+ message: U,
+ color: Color) -> CargoResult<()>
where T: fmt::Display, U: fmt::Display
{
- self.status_with_color(status, message, GREEN)
+ self.print(&status, &message, color, true)
}
pub fn verbose<F>(&mut self, mut callback: F) -> CargoResult<()>
- where F: FnMut(&mut MultiShell) -> CargoResult<()>
+ where F: FnMut(&mut Shell) -> CargoResult<()>
{
match self.verbosity {
- Verbose => callback(self),
+ Verbosity::Verbose => callback(self),
_ => Ok(())
}
}
pub fn concise<F>(&mut self, mut callback: F) -> CargoResult<()>
- where F: FnMut(&mut MultiShell) -> CargoResult<()>
+ where F: FnMut(&mut Shell) -> CargoResult<()>
{
match self.verbosity {
- Verbose => Ok(()),
+ Verbosity::Verbose => Ok(()),
_ => callback(self)
}
}
pub fn error<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
- self.err().say_status("error:", message, RED, false)
+ self.print(&"error:", &message, Red, false)
}
pub fn warn<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
match self.verbosity {
- Quiet => Ok(()),
- _ => self.err().say_status("warning:", message, YELLOW, false),
+ Verbosity::Quiet => Ok(()),
+ _ => self.print(&"warning:", &message, Yellow, false),
}
}
self.verbosity = verbosity;
}
- pub fn set_color_config(&mut self, color: Option<&str>) -> CargoResult<()> {
+ pub fn verbosity(&self) -> Verbosity {
+ self.verbosity
+ }
+
+ pub fn set_color_choice(&mut self, color: Option<&str>) -> CargoResult<()> {
let cfg = match color {
- Some("auto") => Auto,
- Some("always") => Always,
- Some("never") => Never,
+ Some("always") => ColorChoice::Always,
+ Some("never") => ColorChoice::Never,
- None => Auto,
+ Some("auto") |
+ None => ColorChoice::CargoAuto,
Some(arg) => bail!("argument for --color must be auto, always, or \
never, but found `{}`", arg),
};
- self.out.set_color_config(cfg);
- self.err.set_color_config(cfg);
- Ok(())
- }
-
- pub fn get_verbose(&self) -> Verbosity {
- self.verbosity
+ self.choice = cfg;
+ self.err = StandardStream::stderr(cfg.to_termcolor_color_choice());
+ return Ok(());
}
- pub fn color_config(&self) -> ColorConfig {
- assert!(self.out.config.color_config == self.err.config.color_config);
- self.out.config.color_config
+ pub fn color_choice(&self) -> ColorChoice {
+ self.choice
}
}
-impl Shell {
- pub fn create<T: FnMut() -> Box<Write + Send>>(mut out_fn: T, config: ShellConfig) -> Shell {
- let term = match Shell::get_term(out_fn()) {
- Ok(t) => t,
- Err(_) => NoColor(out_fn())
+impl ColorChoice {
+ fn to_termcolor_color_choice(&self) -> termcolor::ColorChoice {
+ return match *self {
+ ColorChoice::Always => termcolor::ColorChoice::Always,
+ ColorChoice::Never => termcolor::ColorChoice::Never,
+ ColorChoice::CargoAuto if isatty() => termcolor::ColorChoice::Auto,
+ ColorChoice::CargoAuto => termcolor::ColorChoice::Never,
};
- Shell {
- terminal: term,
- config: config,
- }
- }
-
- #[cfg(any(windows))]
- fn get_term(out: Box<Write + Send>) -> CargoResult<AdequateTerminal> {
- // Check if the creation of a console will succeed
- if ::term::WinConsole::new(vec![0u8; 0]).is_ok() {
- let t = ::term::WinConsole::new(out)?;
- if !t.supports_color() {
- Ok(NoColor(Box::new(t)))
- } else {
- Ok(Colored(Box::new(t)))
- }
- } else {
- // If we fail to get a windows console, we try to get a `TermInfo` one
- Ok(Shell::get_terminfo_term(out))
- }
- }
-
- #[cfg(any(unix))]
- fn get_term(out: Box<Write + Send>) -> CargoResult<AdequateTerminal> {
- Ok(Shell::get_terminfo_term(out))
- }
-
- fn get_terminfo_term(out: Box<Write + Send>) -> AdequateTerminal {
- // Use `TermInfo::from_env()` and `TerminfoTerminal::supports_color()`
- // to determine if creation of a TerminfoTerminal is possible regardless
- // of the tty status. --color options are parsed after Shell creation so
- // always try to create a terminal that supports color output. Fall back
- // to a no-color terminal regardless of whether or not a tty is present
- // and if color output is not possible.
- match ::term::terminfo::TermInfo::from_env() {
- Ok(ti) => {
- let term = TerminfoTerminal::new_with_terminfo(out, ti);
- if !term.supports_color() {
- NoColor(term.into_inner())
- } else {
- // Color output is possible.
- Colored(Box::new(term))
- }
- },
- Err(_) => NoColor(out),
- }
- }
-
- pub fn set_color_config(&mut self, color_config: ColorConfig) {
- self.config.color_config = color_config;
- }
-
- pub fn say<T: ToString>(&mut self, message: T, color: Color) -> CargoResult<()> {
- self.reset()?;
- if color != BLACK { self.fg(color)?; }
- write!(self, "{}\n", message.to_string())?;
- self.reset()?;
- self.flush()?;
- Ok(())
- }
-
- pub fn say_status<T, U>(&mut self,
- status: T,
- message: U,
- color: Color,
- justified: bool)
- -> CargoResult<()>
- where T: fmt::Display, U: fmt::Display
- {
- self.reset()?;
- if color != BLACK { self.fg(color)?; }
- if self.supports_attr(Attr::Bold) { self.attr(Attr::Bold)?; }
- if justified {
- write!(self, "{:>12}", status.to_string())?;
- } else {
- write!(self, "{}", status)?;
- }
- self.reset()?;
- write!(self, " {}\n", message)?;
- self.flush()?;
- Ok(())
- }
-
- fn fg(&mut self, color: color::Color) -> CargoResult<bool> {
- let colored = self.colored();
-
- match self.terminal {
- Colored(ref mut c) if colored => c.fg(color)?,
- _ => return Ok(false),
- }
- Ok(true)
- }
-
- fn attr(&mut self, attr: Attr) -> CargoResult<bool> {
- let colored = self.colored();
-
- match self.terminal {
- Colored(ref mut c) if colored => c.attr(attr)?,
- _ => return Ok(false)
- }
- Ok(true)
- }
-
- fn supports_attr(&self, attr: Attr) -> bool {
- let colored = self.colored();
-
- match self.terminal {
- Colored(ref c) if colored => c.supports_attr(attr),
- _ => false
- }
- }
-
- fn reset(&mut self) -> term::Result<()> {
- let colored = self.colored();
+ #[cfg(unix)]
+ fn isatty() -> bool {
+ extern crate libc;
- match self.terminal {
- Colored(ref mut c) if colored => c.reset()?,
- _ => ()
+ unsafe { libc::isatty(libc::STDERR_FILENO) != 0 }
}
- Ok(())
- }
-
- fn colored(&self) -> bool {
- self.config.tty && Auto == self.config.color_config
- || Always == self.config.color_config
- }
-}
-impl Write for Shell {
- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- match self.terminal {
- Colored(ref mut c) => c.write(buf),
- NoColor(ref mut n) => n.write(buf)
- }
- }
+ #[cfg(windows)]
+ fn isatty() -> bool {
+ extern crate kernel32;
+ extern crate winapi;
- fn flush(&mut self) -> io::Result<()> {
- match self.terminal {
- Colored(ref mut c) => c.flush(),
- NoColor(ref mut n) => n.flush()
+ unsafe {
+ let handle = kernel32::GetStdHandle(winapi::STD_ERROR_HANDLE);
+ let mut out = 0;
+ kernel32::GetConsoleMode(handle, &mut out) != 0
+ }
}
}
}
extern crate shell_escape;
extern crate tar;
extern crate tempdir;
-extern crate term;
+extern crate termcolor;
extern crate toml;
extern crate url;
-use std::io;
+use std::io::Write;
use std::fmt;
use std::error::Error;
use serde::ser;
use docopt::Docopt;
-use core::{Shell, MultiShell, ShellConfig, Verbosity, ColorConfig};
-use core::shell::Verbosity::{Verbose};
-use term::color::{BLACK};
+use core::Shell;
+use core::shell::Verbosity::Verbose;
pub use util::{CargoError, CargoErrorKind, CargoResult, CliError, CliResult, Config};
println!("{}", encoded);
}
-pub fn shell(verbosity: Verbosity, color_config: ColorConfig) -> MultiShell {
- enum Output {
- Stdout,
- Stderr,
- }
-
- let tty = isatty(Output::Stderr);
-
- let config = ShellConfig { color_config: color_config, tty: tty };
- let err = Shell::create(|| Box::new(io::stderr()), config);
-
- let tty = isatty(Output::Stdout);
-
- let config = ShellConfig { color_config: color_config, tty: tty };
- let out = Shell::create(|| Box::new(io::stdout()), config);
-
- return MultiShell::new(out, err, verbosity);
-
- #[cfg(unix)]
- fn isatty(output: Output) -> bool {
- let fd = match output {
- Output::Stdout => libc::STDOUT_FILENO,
- Output::Stderr => libc::STDERR_FILENO,
- };
-
- unsafe { libc::isatty(fd) != 0 }
- }
- #[cfg(windows)]
- fn isatty(output: Output) -> bool {
- extern crate kernel32;
- extern crate winapi;
-
- let handle = match output {
- Output::Stdout => winapi::winbase::STD_OUTPUT_HANDLE,
- Output::Stderr => winapi::winbase::STD_ERROR_HANDLE,
- };
-
- unsafe {
- let handle = kernel32::GetStdHandle(handle);
- let mut out = 0;
- kernel32::GetConsoleMode(handle, &mut out) != 0
- }
- }
-}
-
-pub fn exit_with_error(err: CliError, shell: &mut MultiShell) -> ! {
+pub fn exit_with_error(err: CliError, shell: &mut Shell) -> ! {
debug!("exit_with_error; err={:?}", err);
let CliError { error, exit_code, unknown } = err;
// exit_code == 0 is non-fatal error, e.g. docopt version info
let fatal = exit_code != 0;
- let hide = unknown && shell.get_verbose() != Verbose;
+ let hide = unknown && shell.verbosity() != Verbose;
if let Some(error) = error {
- let _ignored_result = if hide {
- shell.error("An unknown error occurred")
+ if hide {
+ drop(shell.error("An unknown error occurred"))
} else if fatal {
- shell.error(&error)
+ drop(shell.error(&error))
} else {
- shell.say(&error, BLACK)
- };
+ drop(writeln!(shell.err(), "{}", error))
+ }
if !handle_cause(error, shell) || hide {
- let _ = shell.err().say("\nTo learn more, run the command again \
- with --verbose.".to_string(), BLACK);
+ drop(writeln!(shell.err(), "\nTo learn more, run the command again \
+ with --verbose."));
}
}
std::process::exit(exit_code)
}
-pub fn handle_error(err: CargoError, shell: &mut MultiShell) {
+pub fn handle_error(err: CargoError, shell: &mut Shell) {
debug!("handle_error; err={:?}", &err);
let _ignored_result = shell.error(&err);
handle_cause(err, shell);
}
-fn handle_cause<E, EKind>(cargo_err: E, shell: &mut MultiShell) -> bool
- where E: ChainedError<ErrorKind=EKind> + 'static {
- fn print(error: String, shell: &mut MultiShell) {
- let _ = shell.err().say("\nCaused by:", BLACK);
- let _ = shell.err().say(format!(" {}", error), BLACK);
+fn handle_cause<E, EKind>(cargo_err: E, shell: &mut Shell) -> bool
+ where E: ChainedError<ErrorKind=EKind> + 'static
+{
+ fn print(error: String, shell: &mut Shell) {
+ drop(writeln!(shell.err(), "\nCaused by:"));
+ drop(writeln!(shell.err(), " {}", error));
}
//Error inspection in non-verbose mode requires inspecting the
std::mem::transmute::<&Error, &Error>(r)
}
- let verbose = shell.get_verbose();
+ let verbose = shell.verbosity();
if verbose == Verbose {
//The first error has already been printed to the shell
let dst = resolve_root(dst, config)?;
let dst = metadata(config, &dst)?;
let list = read_crate_list(dst.file())?;
- let mut shell = config.shell();
- let out = shell.out();
for (k, v) in list.v1.iter() {
- writeln!(out, "{}:", k)?;
+ println!("{}:", k);
for bin in v {
- writeln!(out, " {}", bin)?;
+ println!(" {}", bin);
}
}
Ok(())
+use std::collections::BTreeMap;
use std::env;
use std::fs;
+use std::io::Write;
use std::path::Path;
-use std::collections::BTreeMap;
use serde::{Deserialize, Deserializer};
use serde::de;
use git2::Config as GitConfig;
use git2::Repository as GitRepository;
-use term::color::BLACK;
-
use core::Workspace;
use ops::is_bad_artifact_name;
use util::{GitRepo, HgRepo, PijulRepo, internal};
} else {
let new_name = strip_rust_affixes(dir_name);
if new_name != dir_name {
- let message = format!(
- "note: package will be named `{}`; use --name to override",
- new_name);
- config.shell().say(&message, BLACK)?;
+ writeln!(config.shell().err(),
+ "note: package will be named `{}`; use --name to override",
+ new_name)?;
}
Ok(new_name)
}
use crossbeam::{self, Scope};
use jobserver::{Acquired, HelperThread};
-use term::color::YELLOW;
use core::{PackageId, Target, Profile};
use util::{Config, DependencyQueue, Fresh, Dirty, Freshness};
}
Message::Stdout(out) => {
if cx.config.extra_verbose() {
- writeln!(cx.config.shell().out(), "{}", out)?;
+ println!("{}", out);
}
}
Message::Stderr(err) => {
if self.active > 0 {
error = Some("build failed".into());
handle_error(e, &mut *cx.config.shell());
- cx.config.shell().say(
- "Build failed, waiting for other \
- jobs to finish...", YELLOW)?;
+ cx.config.shell().warn(
+ "build failed, waiting for other \
+ jobs to finish...")?;
}
else {
error = Some(e);
use core::{Package, PackageId, PackageSet, Target, Resolve};
use core::{Profile, Profiles, Workspace};
-use core::shell::ColorConfig;
+use core::shell::ColorChoice;
use util::{self, ProcessBuilder, machine_message};
use util::{Config, internal, profile, join_paths, short_hash};
use util::errors::{CargoResult, CargoResultExt};
cmd.arg(&root_path(cx, unit));
- let color_config = cx.config.shell().color_config();
- if color_config != ColorConfig::Auto {
- cmd.arg("--color").arg(&color_config.to_string());
+ match cx.config.shell().color_choice() {
+ ColorChoice::Always => { cmd.arg("--color").arg("always"); }
+ ColorChoice::Never => { cmd.arg("--color").arg("never"); }
+ ColorChoice::CargoAuto => {}
}
if cx.build_config.json_messages {
use std::env;
use std::fs::{self, File};
+use std::io::Write;
use std::iter::repeat;
use std::time::Duration;
use curl::easy::{Easy, SslOpt};
use git2;
use registry::{Registry, NewCrate, NewCrateDependency};
-use term::color::BLACK;
use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET};
}
None => name
};
- config.shell().say(line, BLACK)?;
+ writeln!(config.shell().err(), "{}", line)?;
}
let search_max_limit = 100;
if total_crates > limit as u32 && limit < search_max_limit {
- config.shell().say(
- format!("... and {} crates more (use --limit N to see more)",
- total_crates - limit as u32),
- BLACK)
- ?;
+ writeln!(config.shell().err(),
+ "... and {} crates more (use --limit N to see more)",
+ total_crates - limit as u32)?;
} else if total_crates > limit as u32 && limit >= search_max_limit {
- config.shell().say(
- format!(
- "... and {} crates more (go to http://crates.io/search?q={} to see more)",
- total_crates - limit as u32,
- percent_encode(query.as_bytes(), QUERY_ENCODE_SET)
- ),
- BLACK)
- ?;
+ writeln!(config.shell().err(),
+ "... and {} crates more (go to http://crates.io/search?q={} to see more)",
+ total_crates - limit as u32,
+ percent_encode(query.as_bytes(), QUERY_ENCODE_SET))?;
}
Ok(())
use std::str::FromStr;
use std::sync::{Once, ONCE_INIT};
-use core::MultiShell;
-use core::shell::{Verbosity, ColorConfig};
+use core::Shell;
+use core::shell::Verbosity;
use jobserver;
use serde::{Serialize, Serializer};
use toml;
pub struct Config {
home_path: Filesystem,
- shell: RefCell<MultiShell>,
+ shell: RefCell<Shell>,
rustc: LazyCell<Rustc>,
values: LazyCell<HashMap<String, ConfigValue>>,
cwd: PathBuf,
}
impl Config {
- pub fn new(shell: MultiShell,
+ pub fn new(shell: Shell,
cwd: PathBuf,
homedir: PathBuf) -> Config {
static mut GLOBAL_JOBSERVER: *mut jobserver::Client = 0 as *mut _;
}
pub fn default() -> CargoResult<Config> {
- let shell = ::shell(Verbosity::Verbose, ColorConfig::Auto);
+ let shell = Shell::new();
let cwd = env::current_dir().chain_err(|| {
"couldn't get the current directory of the process"
})?;
self.home_path.join("registry").join("src")
}
- pub fn shell(&self) -> RefMut<MultiShell> {
+ pub fn shell(&self) -> RefMut<Shell> {
self.shell.borrow_mut()
}
};
self.shell().set_verbosity(verbosity);
- self.shell().set_color_config(color.map(|s| &s[..]))?;
+ self.shell().set_color_choice(color.map(|s| &s[..]))?;
self.extra_verbose.set(extra_verbose);
self.frozen.set(frozen);
self.locked.set(locked);
use git2;
use semver;
use serde_json;
-use term;
use toml;
use registry;
SerdeJson(serde_json::Error);
TomlSer(toml::ser::Error);
TomlDe(toml::de::Error);
- Term(term::Error);
ParseInt(num::ParseIntError);
ParseBool(str::ParseBoolError);
Parse(string::ParseError);
&CargoErrorKind::Semver(_) |
&CargoErrorKind::Io(_) |
&CargoErrorKind::SerdeJson(_) |
- &CargoErrorKind::Term(_) |
&CargoErrorKind::ParseInt(_) |
&CargoErrorKind::ParseBool(_) |
&CargoErrorKind::Parse(_) |
use std::io;
use std::path::{Path, PathBuf, Display};
-use term::color::CYAN;
+use termcolor::Color::Cyan;
use fs2::{FileExt, lock_contended_error};
#[allow(unused_imports)]
use libc;
}
}
let msg = format!("waiting for file lock on {}", msg);
- config.shell().status_with_color("Blocking", &msg, CYAN)?;
+ config.shell().status_with_color("Blocking", &msg, Cyan)?;
return block().chain_err(|| {
format!("failed to lock file: {}", path.display())
serde_json = "1.0"
tar = { version = "0.4", default-features = false }
tempdir = "0.3"
-term = "0.4.4"
url = "1.1"
winapi = "0.2"
extern crate serde_json;
extern crate tar;
extern crate tempdir;
-extern crate term;
extern crate url;
#[cfg(windows)] extern crate kernel32;
#[cfg(windows)] extern crate winapi;
fn rust_prefix_stripped() {
assert_that(cargo_process("new").arg("--lib").arg("rust-foo").env("USER", "foo"),
execs().with_status(0)
- .with_stdout("note: package will be named `foo`; use --name to override"));
+ .with_stderr_contains("note: package will be named `foo`; use --name to override"));
let toml = paths::root().join("rust-foo/Cargo.toml");
let mut contents = String::new();
File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
assert_that(cargo_process("search").arg("postgres")
.arg("--host").arg(registry().to_string()),
execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`")
- .with_stdout("\
+ .with_stderr_contains("\
hoare = \"0.1.1\" # Design by contract style assertions for Rust"));
}
assert_that(cargo_process("search").arg("postgres").arg("sql")
.arg("--host").arg(registry().to_string()),
execs().with_status(0)
- .with_stderr("\
-[UPDATING] registry `[..]`")
- .with_stdout("\
+ .with_stderr_contains("\
hoare = \"0.1.1\" # Design by contract style assertions for Rust"));
}
+++ /dev/null
-extern crate cargo;
-extern crate cargotest;
-extern crate hamcrest;
-extern crate term;
-
-use std::io::prelude::*;
-use std::io;
-use std::sync::{Arc, Mutex};
-
-use cargo::core::shell::ColorConfig::{Auto,Always, Never};
-use cargo::core::shell::{Shell, ShellConfig};
-use cargo::util::CargoResult;
-use cargotest::support::{Tap, execs, shell_writes};
-use hamcrest::{assert_that};
-use term::{Terminal, TerminfoTerminal, color};
-
-struct Sink(Arc<Mutex<Vec<u8>>>);
-
-impl Write for Sink {
- fn write(&mut self, data: &[u8]) -> io::Result<usize> {
- Write::write(&mut *self.0.lock().unwrap(), data)
- }
- fn flush(&mut self) -> io::Result<()> { Ok(()) }
-}
-
-#[test]
-fn non_tty() {
- let config = ShellConfig { color_config: Auto, tty: false };
- let a = Arc::new(Mutex::new(Vec::new()));
-
- Shell::create(|| Box::new(Sink(a.clone())), config).tap(|shell| {
- shell.say("Hey Alex", color::RED).unwrap();
- });
- let buf = a.lock().unwrap().clone();
- assert_that(&buf[..], shell_writes("Hey Alex\n"));
-}
-
-#[test]
-fn color_explicitly_disabled() {
- let term = TerminfoTerminal::new(Vec::new());
- if term.is_none() { return }
-
- let config = ShellConfig { color_config: Never, tty: true };
- let a = Arc::new(Mutex::new(Vec::new()));
-
- Shell::create(|| Box::new(Sink(a.clone())), config).tap(|shell| {
- shell.say("Hey Alex", color::RED).unwrap();
- });
- let buf = a.lock().unwrap().clone();
- assert_that(&buf[..], shell_writes("Hey Alex\n"));
-}
-
-#[test]
-fn colored_shell() {
- let term = TerminfoTerminal::new(Vec::new());
- if term.is_none() { return }
-
- let config = ShellConfig { color_config: Auto, tty: true };
- let a = Arc::new(Mutex::new(Vec::new()));
-
- Shell::create(|| Box::new(Sink(a.clone())), config).tap(|shell| {
- shell.say("Hey Alex", color::RED).unwrap();
- });
- let buf = a.lock().unwrap().clone();
- let expected_output = if term.unwrap().supports_color() {
- shell_writes(colored_output("Hey Alex\n", color::RED).unwrap())
- } else {
- shell_writes("Hey Alex\n")
- };
- assert_that(&buf[..], expected_output);
-}
-
-#[test]
-fn color_explicitly_enabled() {
- let term = TerminfoTerminal::new(Vec::new());
- if term.is_none() { return }
- if !term.unwrap().supports_color() { return }
-
- let config = ShellConfig { color_config: Always, tty: false };
- let a = Arc::new(Mutex::new(Vec::new()));
-
- Shell::create(|| Box::new(Sink(a.clone())), config).tap(|shell| {
- shell.say("Hey Alex", color::RED).unwrap();
- });
- let buf = a.lock().unwrap().clone();
- assert_that(&buf[..],
- shell_writes(colored_output("Hey Alex\n",
- color::RED).unwrap()));
-}
-
-#[test]
-fn no_term() {
- // Verify that shell creation is successful when $TERM does not exist.
- assert_that(cargotest::cargo_process().env_remove("TERM"),
- execs().with_stderr(""));
-}
-
-fn colored_output(string: &str, color: color::Color) -> CargoResult<String> {
- let mut term = TerminfoTerminal::new(Vec::new()).unwrap();
- term.reset()?;
- term.fg(color)?;
- write!(&mut term, "{}", string)?;
- term.reset()?;
- term.flush()?;
- Ok(String::from_utf8_lossy(term.get_ref()).to_string())
-}